// 回射服务器基本模型
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BACKLOG 20
#define PORT 8888
#define BUFFSIZE 4096
#define MAXFD 1024
void upper(char buffer[], int len);
void processClient(int clientFd);
int main(void)
{
    int serverFd;
    serverFd = socket(AF_INET, SOCK_STREAM, 0);
    if (serverFd > 0)
    {
        printf("socket created successed.\n");
    }
    else
    {
        printf("socket created failed.\n");
        exit(-1);
    }
    struct sockaddr_in serverAddr;
    memset(&serverAddr, 0, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(PORT);
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    int error = bind(serverFd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
    if (error == 0)
    {
        printf("bind successed.\n");
    }
    else
    {
        printf("bind failed.\n");
        exit(-1);
    }
    error = listen(serverFd, BACKLOG);
    if (error == 0)
    {
        printf("listen successed.\n");
    }
    else
    {
        printf("listen failed.\n");
        exit(-1);
    }
    struct sockaddr_in clientAddr;
    socklen_t clientAddrLen = sizeof clientAddr;
    fd_set originSet;
    FD_ZERO(&originSet);
    int maxFd = serverFd;
    int fdArray[MAXFD] = {0};
    int index = 0;
    fdArray[index++] = serverFd;
    FD_SET(serverFd, &originSet);
    fd_set dealSet = originSet;

    while (1)
    {
        dealSet = originSet;
        printf("start select.\n");
        int ret = select(maxFd+1, &dealSet, NULL, NULL, NULL);
        printf("select return: %d\n", ret);
        for (int i = 0; i < index; ++i)
        {
            printf("judget fdArray index: %d\n", i);
            if (fdArray[i] == -1)
            {
                continue;
            }
            if (!FD_ISSET(fdArray[i], &dealSet))
            {
                continue;
            }
            if (fdArray[i] == serverFd) // 处理服务器监听套接字
            {
                int clientFd = accept(serverFd, (struct sockaddr*)&clientAddr, &clientAddrLen);
                if (clientFd > 0)
                {
                    printf("new connection:\n");
                    printf("port: %d\n", clientAddr.sin_port);
                    char* ip = inet_ntoa(clientAddr.sin_addr);
                    printf("ipv4: %s\n", ip);
                    fdArray[index++] = clientFd;
                    FD_SET(clientFd, &originSet);
                    if (clientFd > maxFd)
                    {
                        maxFd = clientFd;
                    }
                }
                else
                {
                    printf("accept failed.\n");
                    exit(-1);
                }
            }
            else    // 处理客户端套接字
            {
                int curFd = fdArray[i];
                printf("need to read client: %d\n", curFd);
                // processClient(curFd);
                char buffer[BUFFSIZE] = {0};
                int n = recv(curFd, buffer, sizeof buffer, 0);
                if (n > 0)
                {
                    upper(buffer, strlen(buffer));
                    send(curFd, buffer, strlen(buffer)+1, 0);
                }
                else
                {
                    printf("error\n");
                    FD_CLR(curFd, &originSet);
                    fdArray[i] = -1;
                    // exit(-1);
                }
            }
        }
    }

    return 0;
}
void upper(char buffer[BUFFSIZE], int len)
{
    for (int i = 0; i < len; ++i)
    {
        if (buffer[i] < 97 || buffer[i] > 122)
        {
            continue;
        }
        buffer[i] -= 32;
    }
}
void processClient(int clientFd)
{
    // char buffer[BUFFSIZE] = "welcome to my server.\n";
    // send(clientFd, buffer, strlen(buffer), 0);
    // while (1)
    // {
    //     int n = recv(clientFd, buffer, sizeof buffer, 0);
    //     printf("%s\n", buffer);
    //     printf("recv %d bytes data altogether.\n", n);
    //     upper(buffer, strlen(buffer));
    //     send(clientFd, buffer, strlen(buffer)+1, 0);
    // }
    char buffer[BUFFSIZE] = {0};
    int n = recv(clientFd, buffer, sizeof buffer, 0);
    if (n > 0)
    {
        upper(buffer, strlen(buffer));
        send(clientFd, buffer, strlen(buffer)+1, 0);
    }
    else
    {
        printf("error\n");
        exit(-1);
    }

}